#!/usr/bin/env jruby
# -*- coding: utf-8 -*-
# Can also be run by any compliant ruby.

# This script is for use with JRuby, to copy the (patched) stdlib and external test files from
# various locations in MRI's layout to JRuby's layout. It should be used
# against the jruby-specific fork of MRI's repository at github.com/jruby/ruby.
#
# This script selects the branch to use against with the version number, i.e: jruby-ruby_2_2_0.
#
# usage: sync_ruby <tests|stdlib|all> <version(2_2_0)> <jruby ruby fork clone> <jruby dir>
#
# Example:
#
# Suppose the JRuby ruby fork is in ../jruby-ruby, and jruby is in the current directory.
# We want to sync the 2.2.0 standard libraries.
#
# $ jruby tool/sync_ruby stdlib 2_2_0 ../jruby-ruby .
# Already on 'jruby-ruby_2_2_0'
# cp -r ../jruby-ruby/lib/English.rb ./lib/ruby/1.8
# cp -r ../jruby-ruby/lib/Env.rb ./lib/ruby/1.8
# ...
#
# Layout mapping lives in globals_<version>.rb.

require 'fileutils'

class Sync
  include FileUtils

  def initialize(type, version, source, target)
    @type = type
    @named_version = version
    @version = format_version(version)
    @source = source
    @target = target

    checkout
  end

  def sync_tests
    Dir.glob("#{@source}/test/*") do |file|
      next if file =~ /\/excludes$/
      cp_r file, "#{@target}/test/mri", :verbose => true
    end
  end

  def sync_stdlib
    load File.dirname(__FILE__) + "/sync_ruby_files.rb"

    for file in STDLIB_FILES
      cp_r "#{@source}/lib/#{file}", "#{@target}/lib/ruby/stdlib", :verbose => true
    end

    for file, target in EXT_FILES
      if file !~ /.rb$/
        mkdir_p "#{@source}/#{file}"
        cp_r "#{@source}/#{file}", "#{@target}/lib/ruby/stdlib/#{target}/..", :verbose => true
      else
        cp_r "#{@source}/#{file}", "#{@target}/lib/ruby/stdlib/#{target}", :verbose => true
      end
    end
  end

  private
  def format_version(version)
    version.gsub(/_\d+$/, '').gsub(/_/, '.')
  end

  def checkout
    cd(@source) do
      branch = "jruby-ruby#{@type == 'rubygems' ? 'gems' : ''}_#{@named_version}"

      if (branches = `git branch | sed 's/[\*\s]*//'`).split("\n").include? branch
        `git checkout #{branch}`
      else
        `git checkout -t origin/#{branch}`
      end
    end
  end
end

if $0 == __FILE__
  if ARGV.size != 4
    abort "usage: sync_ruby <tests|stdlib|all> <version(2_2_0)> <jruby ruby fork clone> <jruby dir>"
  end

  what, version, source, target = ARGV

  if !%w{tests stdlib all}.include? what
    abort "invalid source to sync: #{what}"
  end

  if !(version =~ /^\d_\d_\d$/)
    abort "invalid version number: #{version}"
  end

  if !File.exist?(source) || !File.directory?(source)
    abort "invalid source dir: #{source}"
  end

  if !File.exist?(target) || !File.directory?(target)
    abort "invalid target dir: #{target}"
  end

  sync = Sync.new(what, version, source, target)
  if what == 'all'
    sync.sync_tests
    sync.sync_stdlib
  else
    sync.send(:"sync_#{what}")
  end
end
